// 游戏参数
const ROWMAX = 10   // 行数
const COLMAX = 10   // 列数

// 游戏的当前状态（不需要响应式渲染）
const gameStatus = {
  curDir: 'L',  // 当前的方向
  outOfBound: false,
  duang: false, // 撞到自己
}

// 辅助工具
const utils = {
  /**
   * 即将要到达的坐标是否在界内
   * @param {坐标} go_to 即将要到达的坐标
   */
  isWithinBound(go_to){
    return go_to[0] >= 0 && go_to[0] < ROWMAX && 
      go_to[1] >= 0 && go_to[1] < COLMAX
  },
  // 两个坐标是否相等
  isCoorSame(a, b) {
    return a[0] === b[0] && a[1] === b[1]
  },
  // 坐标是否在蛇身上
  isInSnake(a, snake) {
    return snake.some(b => this.isCoorSame(a, b))
  },
  // 随机生成坐标
  genCoor(){
    let x = Math.floor(Math.random()*ROWMAX)
    let y = Math.floor(Math.random()*COLMAX)
    return [x,y]
  },
  // 随机生成食物
  genFood(snake){
    do {
      var food = this.genCoor()
    } while (this.isInSnake(food, snake));
    return food
  },
}

const game = new Vue({
  el: '#game',
  data: {
    snake: [],  // 蛇身坐标，初始时随机生成蛇头
    food: undefined,
  },
  computed: {
    head(){
      return this.snake[0]
    }
  },
  methods : {
    // 开始游戏
    start(){
      console.log('🚀 游戏开始了');
      this.init()
      let timer = setInterval(() => {
        this.go()
        if (gameStatus.outOfBound || gameStatus.duang) {
          // 游戏结束
          clearInterval(timer)
        }
      },600)
    },
    // 向前一步
    go(){
      let curDir = gameStatus.curDir
      let go_to = undefined // 即将要移到的坐标点
      let head = this.head
      let snake = this.snake
      switch (curDir) {
        case 'L':
          go_to = [head[0], head[1]-1]
          break;
        case 'R':
          go_to = [head[0], head[1]+1]
          break;
        case 'U':
          go_to = [head[0]-1, head[1]]
          break;
        case 'D':
          go_to = [head[0]+1, head[1]]
          break;
      }
      
      if(utils.isWithinBound(go_to)) { 
        // 撞到自己
        if (utils.isInSnake(go_to, snake)) {
          console.log('😱 duang!!, game over!! ');
          gameStatus.duang = true;
        }
        // 遇到食物
        else if (utils.isCoorSame(this.food, go_to)) {
          // 蛇长+1 ，重新生成食物
          snake.unshift(go_to)
          this.food = utils.genFood(snake)
          console.log('😋 eat food ');
        } else {
          // 什么都没有
          snake.unshift(go_to)
          snake.pop()
        }
      }else {
        console.log('😳 out of bound, game over!! ');
        gameStatus.outOfBound = true
      }
    },
    init(){
      this.snake.push(utils.genCoor())
      this.food = utils.genFood(this.snake)
    },
    // 键盘控制事件响应
    keyHandler(dir){
      gameStatus.curDir = dir
      console.log('⤴ turn to ' + dir);
    },
    
    cellClass(r,c){
      let res = ''
      for (const coor of this.snake) {
        if (utils.isCoorSame([r,c], coor)) {
          res = 'S'
          break
        }
        if (utils.isCoorSame([r,c], this.food)) {
          res = 'F'
          break
        }
      }
      return res
    }
  }
})

// 注册键盘控制事件
window.addEventListener('keydown', function(e) {
  const map = {
    '37': 'L',
    '38': 'U',
    '39': 'R',
    '40': 'D',
  }
  let key = map[e.keyCode]
  if (key) {
    game.keyHandler(key)
  }
})

game.start()